package com.atguigu.tingshu.album.listenner;


import com.alibaba.fastjson.JSONObject;
import com.atguigu.tingshu.album.service.MqOpsService;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.vo.album.TrackStatMqVo;
import com.rabbitmq.client.Channel;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;


@Component
@Slf4j
public class AlbumInfoListenner {




    @Autowired
    private MqOpsService mqOpsService;
    @Autowired
    private StringRedisTemplate redisTemplate;

    private  Integer maxRetryCount = 3;

    @SneakyThrows
    @RabbitListener(bindings = {@QueueBinding(value = @Queue(value = MqConst.QUEUE_TRACK_STAT_UPDATE,durable = "true"),
            exchange = @Exchange(value = MqConst.EXCHANGE_TRACK,durable = "true"),
            key ={MqConst.ROUTING_TRACK_STAT_UPDATE}
    )})
    public void trackAndAlbumStateTypeUpdate(String content, Message message, Channel channel){
        log.info("下游专辑微服务接收到上游用户微服务的更新播放量的消息{},并完成对不同维度的更新",content);
        //1.判断下游消费者是否获取到了消息
        if (StringUtils.isEmpty(content)){
            return ; //不用消费了
        }
        //2.获取消息(未来对获取的消息进行消息解析)
        TrackStatMqVo trackStatMqVo = JSONObject.parseObject(content, TrackStatMqVo.class);
        String businessNo = trackStatMqVo.getBusinessNo();//(唯一标识)业务编号：去重使用
        //4.1获取消息的唯一标识
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        //3.消费消息
        int count= 0;
        try {
            //4.手动应答,消费
            count = mqOpsService.trackAndAlbumStateTypeUpdate(trackStatMqVo);
            channel.basicAck(deliveryTag,false); //一条一条手动确认,不是批量确认
        } catch (GuiguException e) {
            log.info("消费者再消费消息:{}失败,开始准备重试",content);
            Long increment = redisTemplate.opsForValue().increment("customer:mgs:retry" + businessNo);
            //消息继续回到队列,重试三次
            if (increment<=maxRetryCount){
                channel.basicNack(deliveryTag,false,true);
                log.info("消息:{}进行重试:{}次",businessNo,increment);
            }else {
                //如果三次到了 消息就别进队列了 让mq删除这条消息 再记录日志 人为的排查
                log.info("消息:{}进行重试超过最大值,不再重试,请认为的排查,原因是:{}",businessNo,e.getMessage());
                channel.basicNack(deliveryTag,false,false);
            }
            throw new RuntimeException(e);
        }
        catch (Exception e){
            //处理手动确认失败
            log.info("消息消费成功,但是服务端确认应答是网络出现抖动,消息直接从队列中删除");
            channel.basicNack(deliveryTag,false,false);
        }
    }
}
